# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <termios.h>
# include <fcntl.h>
# include <string.h>
# include <sys/time.h>
# include <sys/types.h>
# include <pthread.h>

int fd,i;
pthread_t thread[2];
pthread_mutex_t mut;

/****************************************************************************
结构体说明：传送控制单片机的信息
成员1：select 选择功能模块
成员2：control 控制单片机相应的动作
*****************************************************************************/
struct protocal
{
    unsigned char select;
    unsigned char control;
};
struct protocal ptr[14]={{0xa1,0x01},{0xa1,0x02},{0xa1,0x03},{0xa1,0x04},{0xa1,0x05},
                        {0xa1,0x06},{0xa1,0x07},{0xa1,0x08},{0xb2,0x00},{0xb2,0x03},
                        {0xb2,0x06},{0xb2,0x09},{0xb2,0x0e},{0xc3,0xd4}};

/********************************************************************
功能说明：设置linux串口参数
传入参数：   
fd             nspeed     nbit        nevent      nstop
文件句柄     波特率     数据位     奇偶校验     停止位
返回值: fd 文件句柄
********************************************************************/                       
int set_port(int fd ,int nspeed ,int nbits ,char nevent ,int nstop)
{
    struct termios newtio,oldtio;
    if (tcgetattr(fd,&oldtio)!= 0)
    {
        perror("setup serial");
        return -1;
    }
    bzero(&newtio,sizeof(newtio));
    newtio.c_cflag |= CLOCAL|CREAD;
    newtio.c_cflag &= ~CSIZE;
    switch (nbits)
    {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }
    switch (nevent)
    {
        case 'N':
            newtio.c_cflag &= ~PARENB;
            break;
    }
    switch (nspeed)
    {
        case 9600:
            cfsetispeed(&newtio,B9600);
            cfsetospeed(&newtio,B9600);
            break;
    }
    switch (nstop)
    {
        case 1:
            newtio.c_cflag &= ~CSTOPB;
            break;
        case 2:
            newtio.c_cflag |= CSTOPB;
            break;
    }
    newtio.c_cc[VTIME]= 0;
    newtio.c_cc[VMIN]= 14;
    tcflush(fd,TCIFLUSH);
    if ((tcsetattr(fd,TCSANOW,&newtio))!= 0)
    {
        perror("com set");
        return -1;
    }
    return 0;
}

int open_port(int fd,int comport)
{
    if (comport == 1){
        fd = open ("/dev/ttyUSB0",O_RDWR);
        if ( -1 == fd ){
            perror("can't open serial port");
            return -1;
        }
    }
    return fd;
}

void write_port(void)
{
    int nwrite;
    for (i=0;i<14;i++)
    {
        nwrite = write(fd,&ptr[i],2);
        usleep(200000);/*每200ms秒发一次数据*/
    }   
    return;
}

void read_port(void)
{   
    fd_set rd;
    int nread,retval;
    unsigned char msg[66];
    struct timeval timeout;
    FD_ZERO(&rd);
    FD_SET(fd,&rd);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    retval = select (fd+1,&rd,NULL,NULL,&timeout);/*select 实现i/o复用*/
    switch (retval)
    {
        case 0:
            printf("no data input within  1 seconds.\n");
            break;
        case -1:
            perror("select");
            break;       
        default:
            if((nread=read(fd,msg,66))>0)
            {
                printf("nread=%d,msg=%s\n",nread,msg);
		//printf("nread=%d,msg=%d\n",nread,msg);
            }
            break;
    }
}

void *recv_thread()
{
    pthread_mutex_lock(&mut);
    read_port();
    pthread_mutex_unlock(&mut);
    pthread_exit(NULL);
}

void *send_thread()
{
    pthread_mutex_lock(&mut);
    write_port();
    pthread_mutex_unlock(&mut);
    pthread_exit(NULL);
}

void create_thread(void)
{
    int temp;
    memset(thread, 0, sizeof(thread));
    if((temp = pthread_create(&thread[0], NULL,(void *)write_port, NULL)) != 0)
        printf("create send_thread failed!\n");        
    if((temp = pthread_create(&thread[1], NULL,(void *)read_port, NULL)) != 0)
        printf("create recev_thread failed!\n");
       
}

void wait_thread(void)
{
    if(thread[0] !=0)
    {
        pthread_join(thread[0],NULL);
        printf("send_thread end\n");
    }
    if(thread[1] !=0)
    {
        pthread_join(thread[1],NULL);
        printf("recev_thread end\n");
    }
}


int  main()
{   
    if((fd=open_port(fd,1))<0){
        perror("open_port error");
    }
    if((i=set_port(fd,9600,8,'N',1))<0){
        perror("set_opt error");
    }
    /*用默认属性初始化互斥锁*/
    pthread_mutex_init(&mut,NULL);   
    while (1)
    {
        create_thread();
        wait_thread();
    }
   
    close(fd);
    return 0;
}
